#!/bin/bash

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 初始化配置
DEFAULT_CONTAINER_NAME="gougu"
declare -A IMAGE_PORTS=(
    ["mfkd1000/gougubt"]="6050 6051 6052 6053"
    ["mfkd1000/gougu"]="6061 6062 6071 6072 6081 6082"
    ["registry.cn-hangzhou.aliyuncs.com/mfkd1000/gougubt"]="6050 6051 6052 6053"
    ["registry.cn-hangzhou.aliyuncs.com/mfkd1000/gougu"]="6061 6062 6071 6072 6081 6082"
)
DEFAULT_PORTS=()
USED_PORTS=()
ASSIGNED_PORTS=()
AUTO_SELECTION=false
COMPOSE_CMD=""

# 检测并设置compose命令
detect_compose_command() {
    if docker compose version &>/dev/null; then
        COMPOSE_CMD="docker compose"
        echo -e "${GREEN}[系统] 使用Docker Compose V2插件${NC}"
    elif command -v docker-compose &>/dev/null; then
        COMPOSE_CMD="docker-compose"
        echo -e "${YELLOW}[系统] 使用Docker Compose V1独立命令${NC}"
    else
        echo -e "${RED}错误：未检测到Docker Compose命令${NC}"
        exit 1
    fi
}

# 生成唯一容器名称（支持自定义）
generate_unique_name() {
    local base_name="$1"
    local name=""

    read -p "请输入容器名称 (默认: ${base_name}): " custom_name
    name="${custom_name:-$base_name}"

    # 检查名称合法性
    while [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; do
        echo -e "${RED}错误：名称只能包含字母、数字、- 和 _${NC}" >&2
        read -p "请重新输入容器名称: " name
    done

    # 检查是否已存在，如果存在则要求手动输入
    while docker ps -a --format '{{.Names}}' | grep -qw "$name"; do
        echo -e "${RED}错误：容器名称 '$name' 已存在！${NC}" >&2
        read -p "请重新输入一个不同的容器名称: " name
        
        # 再次检查名称合法性
        while [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; do
            echo -e "${RED}错误：名称只能包含字母、数字、- 和 _${NC}" >&2
            read -p "请重新输入容器名称: " name
        done
    done

    echo "$name"
}

# 精准系统检测
detect_system() {
    # 检测群辉DSM
    if [ -f /etc/synoinfo.conf ] && [ -d /var/packages ]; then
        echo "dsm"
        return
    fi

    # 检测FNOS系统（使用 /vol* 目录）
    if grep -q "ID=debian" /etc/os-release && ls /vol* &>/dev/null; then
        echo "fnos"
        return
    fi

    # 检测其他Debian系统
    if grep -q "ID=debian" /etc/os-release; then
        echo "debian"
        return
    fi

    # 其他Linux系统
    if [ -f /etc/os-release ]; then
        echo "linux"
        return
    fi

    echo "unknown"
}

# 查找Docker目录
get_docker_dir() {
    local system_type=$1
    local dir=""

    case $system_type in
        "dsm")
            # 查找现有的 docker 目录，找到就用第一个
            dir=$(find /volume* -maxdepth 1 -type d -name "docker" 2>/dev/null | head -n1)
            # 如果没找到，就使用默认路径 /volume1/docker
            [ -z "$dir" ] && dir="/volume1/docker"
            ;;
        "fnos")
            # 查找现有的 docker 目录，优先在 /vol*/1000 下查找
            dir=$(find /vol*/1000 -maxdepth 1 -type d -name "docker" 2>/dev/null | head -n1)
            # 如果没找到，尝试在 /vol* 的其他位置查找
            if [ -z "$dir" ]; then
                dir=$(find /vol* -maxdepth 2 -type d -name "docker" 2>/dev/null | head -n1)
            fi
            # 如果还是没找到，就使用默认路径 /vol1/1000/docker
            [ -z "$dir" ] && dir="/vol1/1000/docker"
            ;;
        *)
            # 其他系统直接使用 /opt/docker
            dir="/opt/docker"
            ;;
    esac

    # 清理路径中的特殊字符
    dir=$(echo "$dir" | tr -d '\n\r')
    
    # 创建目录（如果不存在）
    if ! mkdir -p "$dir"; then
        echo -e "${RED}无法创建目录 $dir${NC}" >&2
        exit 1
    fi
    
    echo "$dir"
}

# 获取Docker目录
find_docker_dirs() {
    local system_type
    system_type=$(detect_system)
    echo -e "${BLUE}检测到系统类型: ${system_type}${NC}" >&2  # 改为输出到stderr，避免被捕获
    get_docker_dir "$system_type"
}

# 打印分隔线
print_separator() {
    echo -e "${BLUE}========================================${NC}"
}

# 检测依赖
check_requirements() {
    if ! command -v docker &>/dev/null; then
        echo -e "${RED}错误：需要安装Docker${NC}" >&2
        exit 1
    fi
}

# 获取已用端口
get_used_ports() {
    USED_PORTS=()
    USED_PORTS+=($(docker ps --format '{{.Ports}}' | grep -oP '\d+(?=/tcp)' | sort -u))
    if command -v ss &>/dev/null; then
        USED_PORTS+=($(ss -tuln | awk '{print $5}' | grep -oP '(?<=:)\d+$' | sort -u))
    else
        USED_PORTS+=($(netstat -tuln | awk '{print $4}' | grep -oP '(?<=:)\d+$' | sort -u))
    fi
    USED_PORTS=($(printf "%s\n" "${USED_PORTS[@]}" | sort -un))
}

# 检查端口可用性
is_port_available() {
    ! printf '%s\n' "${USED_PORTS[@]}" | grep -qx "$1"
}

# 检查端口是否已分配
is_port_assigned() {
    printf '%s\n' "${ASSIGNED_PORTS[@]}" | grep -qx "$1"
}

# 端口选择器
port_selector() {
    local container_port=$1
    local preferred_port=$2
    local port=""
    local max_attempts=5

    print_separator
    echo -e "${YELLOW}配置容器端口 ${container_port} 的映射:${NC}"

    for ((attempt=1; attempt<=max_attempts; attempt++)); do
        [ ${#ASSIGNED_PORTS[@]} -gt 0 ] && echo -e "${GREEN}已分配端口: ${ASSIGNED_PORTS[*]}${NC}"

        read -p "请输入主机端口 (默认${preferred_port}): " input_port
        port=${input_port:-$preferred_port}

        if ! [[ "$port" =~ ^[0-9]+$ ]]; then
            echo -e "${RED}错误：必须输入数字${NC}" >&2
        elif ((port < 1 || port > 65535)); then
            echo -e "${RED}错误：端口范围必须是1-65535${NC}" >&2
        elif ! is_port_available "$port"; then
            echo -e "${RED}错误：端口 ${port} 已被系统占用${NC}" >&2
        elif is_port_assigned "$port"; then
            echo -e "${RED}错误：端口 ${port} 已分配使用${NC}" >&2
        else
            ASSIGNED_PORTS+=("$port")
            USED_PORTS+=("$port")
            echo -e "${GREEN}映射成功: ${port} → ${container_port}${NC}"
            return 0
        fi

        [ $attempt -lt $max_attempts ] && echo -e "${YELLOW}剩余尝试次数: $((max_attempts - attempt))${NC}"
    done

    echo -e "${RED}错误：无法为容器端口 ${container_port} 分配主机端口${NC}" >&2
    exit 1
}

# 生成docker-compose配置（放到data目录的上级目录）
generate_compose_file() {
    local data_path="$1"
    local compose_dir=$(dirname "$data_path")  # 获取data目录的上级目录
    
    cat > "${compose_dir}/docker-compose.yml" <<EOF
services:
  ${CONTAINER_NAME}:
    image: ${IMAGE_NAME}
    container_name: ${CONTAINER_NAME}
    restart: always
    ports:
$(
    for i in "${!DEFAULT_PORTS[@]}"; do
        echo "      - \"${ASSIGNED_PORTS[i]}:${DEFAULT_PORTS[i]}\""
    done
)
    volumes:
      - "${data_path}:/data"
    tty: true
EOF
    echo -e "${GREEN}已生成 docker-compose.yml 配置文件到: ${compose_dir}/${NC}"
}

# 主安装流程
main() {
    check_requirements
    detect_compose_command
    get_used_ports

    echo -e "\n${GREEN}=== Gougu Docker 安装向导 ===${NC}"
    print_separator

    # 使用临时变量来捕获容器名称，避免错误信息污染
    local temp_container_name
    temp_container_name=$(generate_unique_name "$DEFAULT_CONTAINER_NAME")
    CONTAINER_NAME="$temp_container_name"
    echo -e "${GREEN}使用的容器名称: ${CONTAINER_NAME}${NC}"

    echo -e "\n${GREEN}选择Docker镜像:${NC}"
    select IMAGE_OPTION in "mfkd1000/gougubt" "mfkd1000/gougu" "registry.cn-hangzhou.aliyuncs.com/mfkd1000/gougubt" "registry.cn-hangzhou.aliyuncs.com/mfkd1000/gougu" "自定义镜像"; do
        case $REPLY in
            1|2|3|4) 
                IMAGE_NAME="$IMAGE_OPTION"
                DEFAULT_PORTS=(${IMAGE_PORTS[$IMAGE_NAME]})
                echo -e "${BLUE}已加载镜像 ${IMAGE_NAME} 的默认端口: ${DEFAULT_PORTS[*]}${NC}"
                break ;;
            5) 
                while :; do
                    read -p "请输入镜像名称: " IMAGE_NAME
                    [ -n "$IMAGE_NAME" ] && break
                    echo -e "${RED}镜像名称不能为空!${NC}" >&2
                done
                read -p "请输入该镜像的容器端口（空格分隔）: " CUSTOM_PORTS
                DEFAULT_PORTS=($CUSTOM_PORTS)
                break ;;
            *) echo -e "${RED}无效选择!${NC}" >&2 ;;
        esac
    done

    # 获取Docker目录（不包含调试信息）
    DEFAULT_DOCKER_DIR=$(get_docker_dir "$(detect_system)")
    DEFAULT_DATA_DIR="${DEFAULT_DOCKER_DIR}/${CONTAINER_NAME}/data"
    
    echo -e "\n${GREEN}数据目录选择${NC}"
    echo -e "系统推荐目录: ${YELLOW}${DEFAULT_DATA_DIR}${NC}"
    read -p "请输入数据目录路径 (默认推荐目录): " input_path
    DATA_PATH=$(realpath -m "${input_path:-$DEFAULT_DATA_DIR}")
    
    mkdir -p "$DATA_PATH" || {
        echo -e "${RED}无法创建数据目录: ${DATA_PATH}${NC}" >&2
        exit 1
    }
    echo -e "最终数据目录: ${GREEN}${DATA_PATH}${NC}"

    echo -e "\n${GREEN}端口配置模式选择${NC}"
    select mode in "手动指定每个端口" "自动分配所有端口"; do
        case $REPLY in
            1) AUTO_SELECTION=false; break ;;
            2) AUTO_SELECTION=true; break ;;
            *) echo -e "${RED}无效选择!${NC}" >&2 ;;
        esac
    done

    echo -e "\n${GREEN}开始端口配置${NC}"
    for container_port in "${DEFAULT_PORTS[@]}"; do
        if $AUTO_SELECTION; then
            # 优先尝试使用与容器相同的端口
            if is_port_available "$container_port" && ! is_port_assigned "$container_port"; then
                ASSIGNED_PORTS+=("$container_port")
                USED_PORTS+=("$container_port")
                echo -e "自动分配: ${GREEN}${container_port} → ${container_port} (优先使用相同端口)${NC}"
            else
                # 如果相同端口不可用，则寻找最近的可用端口
                local offset=1
                while :; do
                    # 尝试比容器端口大的端口
                    local higher_port=$((container_port + offset))
                    if (( higher_port <= 65535 )) && 
                       is_port_available "$higher_port" && 
                       ! is_port_assigned "$higher_port"; then
                        ASSIGNED_PORTS+=("$higher_port")
                        USED_PORTS+=("$higher_port")
                        echo -e "自动分配: ${GREEN}${higher_port} → ${container_port}${NC}"
                        break
                    fi
                    
                    # 尝试比容器端口小的端口
                    local lower_port=$((container_port - offset))
                    if (( lower_port >= 1 )) && 
                       is_port_available "$lower_port" && 
                       ! is_port_assigned "$lower_port"; then
                        ASSIGNED_PORTS+=("$lower_port")
                        USED_PORTS+=("$lower_port")
                        echo -e "自动分配: ${GREEN}${lower_port} → ${container_port}${NC}"
                        break
                    fi
                    
                    # 如果上下端口都不可用，增加偏移量继续查找
                    ((offset++))
                    if (( offset > 100 )); then
                        echo -e "${RED}错误：无法为容器端口 ${container_port} 找到可用端口${NC}" >&2
                        exit 1
                    fi
                done
            fi
        else
            port_selector "$container_port" "$container_port"
        fi
    done

    generate_compose_file "$DATA_PATH"

    # 获取docker-compose.yml所在的目录（data目录的上级目录）
    COMPOSE_DIR=$(dirname "$DATA_PATH")
    
    echo -e "\n${GREEN}正在启动容器...${NC}"
    if (cd "$COMPOSE_DIR" && $COMPOSE_CMD up -d); then
        print_separator
        echo -e "${GREEN}✓ 容器启动成功!${NC}"
        echo -e "容器名称: ${CONTAINER_NAME}"
        echo -e "使用镜像: ${IMAGE_NAME}"
        echo -e "数据目录: ${DATA_PATH}"
        echo -e "Compose文件: ${COMPOSE_DIR}/docker-compose.yml"
        echo -e "端口映射:"
        for i in "${!DEFAULT_PORTS[@]}"; do
            echo -e "  ${ASSIGNED_PORTS[i]} → ${DEFAULT_PORTS[i]}"
        done
        print_separator
    else
        echo -e "${RED}容器启动失败!${NC}" >&2
        exit 1
    fi
}

main